package com.yuelao.yuelao_backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuelao.yuelao_backend.common.BizException;
import com.yuelao.yuelao_backend.common.ErrorCode;
import com.yuelao.yuelao_backend.dto.CoinTransactionDTO;
import com.yuelao.yuelao_backend.entity.CoinTransaction;
import com.yuelao.yuelao_backend.entity.User;
import com.yuelao.yuelao_backend.entity.UserCoinAccount;
import com.yuelao.yuelao_backend.entity.VipPlan;
import com.yuelao.yuelao_backend.mapper.CoinTransactionMapper;
import com.yuelao.yuelao_backend.mapper.UserCoinAccountMapper;
import com.yuelao.yuelao_backend.mapper.UserMapper;
import com.yuelao.yuelao_backend.mapper.VipPlanMapper;
import com.yuelao.yuelao_backend.service.AchievementService;
import com.yuelao.yuelao_backend.service.CoinService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import jakarta.annotation.Resource;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 爱心币Service实现类
 * 重构说明：适配新的UserCoinAccount表结构，金额使用Integer（以分为单位）
 */
@Service
public class CoinServiceImpl extends ServiceImpl<CoinTransactionMapper, CoinTransaction> implements CoinService {

    @Resource
    private UserCoinAccountMapper userCoinAccountMapper;
    
    @Resource
    private UserMapper userMapper;
    
    @Resource
    private VipPlanMapper vipPlanMapper;
    
    @Resource
    private AchievementService achievementService;
    
    // 默认转账手续费率（1%）
    private static final double DEFAULT_TRANSFER_FEE_RATE = 0.01;

    @Override
    public Map<String, Object> getCoinBalance(Long userId) {
        UserCoinAccount account = getUserCoinAccount(userId);
        
        String levelStr = account.getLevel() != null ? account.getLevel() : "bronze";
        int levelNum = getLevelNumber(levelStr);
        String levelDisplayName = getLevelDisplayName(levelStr);
        
        Map<String, Object> result = new HashMap<>();
        result.put("balance", account.getLoveCoin() != null ? account.getLoveCoin() : 0);
        result.put("level", levelStr);
        result.put("levelNum", levelNum);
        result.put("levelDisplayName", levelDisplayName);
        result.put("totalEarned", account.getTotalEarned() != null ? account.getTotalEarned() : 0);
        result.put("totalSpent", account.getTotalSpent() != null ? account.getTotalSpent() : 0);
        result.put("nextUpgradeCost", levelNum < 6 ? getUpgradeCost(levelNum + 1) : 0);
        return result;
    }
    
    /**
     * 获取等级显示名称
     * @param levelName 等级名称
     * @return 等级显示名称
     */
    private String getLevelDisplayName(String levelName) {
        if (levelName == null) return "铜牌";
        
        switch (levelName) {
            case "铜牌": return "铜牌";
            case "银牌": return "银牌";
            case "金牌": return "金牌";
            case "钻石": return "钻石";
            case "大师": return "大师";
            case "传说": return "传说";
            default: return "铜牌";
        }
    }

    @Override
    public List<CoinTransactionDTO> getTransactionHistory(Long userId, int pageNum, int pageSize, String type) {
        Page<CoinTransaction> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<CoinTransaction> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CoinTransaction::getUserId, userId);
        
        if (type != null && !type.isEmpty()) {
            queryWrapper.eq(CoinTransaction::getType, type);
        }
        
        queryWrapper.orderByDesc(CoinTransaction::getCreatedAt);

        Page<CoinTransaction> transactionPage = page(page, queryWrapper);
        return transactionPage.getRecords().stream()
                .map(this::convertToCoinTransactionDTO)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean spendCoins(Long userId, Integer amount, String source, String title,
                             String description, Long relatedId, String relatedType) {
        if (amount == null || amount <= 0) {
            throw new BizException(ErrorCode.PARAMS_ERROR, "消费金额必须大于0");
        }

        // 1. 获取用户账户
        UserCoinAccount account = getUserCoinAccount(userId);
        
        // 2. 检查余额
        Integer currentBalance = account.getLoveCoin() != null ? account.getLoveCoin() : 0;
        if (currentBalance < amount) {
            throw new BizException(ErrorCode.OPERATION_ERROR, "爱心币余额不足");
        }

        // 3. 更新账户余额
        Integer balanceBefore = currentBalance;
        Integer balanceAfter = currentBalance - amount;
        account.setLoveCoin(balanceAfter);
        account.setTotalSpent((account.getTotalSpent() != null ? account.getTotalSpent() : 0) + amount);
        account.setUpdatedAt(LocalDateTime.now());
        userCoinAccountMapper.updateById(account);
        
        // 检查爱心币余额相关成就
        achievementService.checkCoinBalanceAchievements(userId, balanceAfter);
        
        // 检查消费相关成就
        achievementService.checkSpendingAchievements(userId, amount, false);

        // 4. 记录交易
        CoinTransaction transaction = new CoinTransaction();
        transaction.setUserId(userId);
        transaction.setType("spend");
        transaction.setAmount(-amount); // 消费为负数
        transaction.setFeeAmount(0);
        transaction.setBalanceBefore(balanceBefore);
        transaction.setBalanceAfter(balanceAfter);
        transaction.setSource(source);
        transaction.setTitle(title);
        transaction.setDescription(description);
        transaction.setRelatedId(relatedId);
        transaction.setRelatedType(relatedType);
        transaction.setCreatedAt(LocalDateTime.now());
        return save(transaction);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addCoins(Long userId, Integer amount, String source, String title,
                           String description, Long relatedId, String relatedType) {
        if (amount == null || amount <= 0) {
            throw new BizException(ErrorCode.PARAMS_ERROR, "增加金额必须大于0");
        }

        // 1. 获取用户账户
        UserCoinAccount account = getUserCoinAccount(userId);
        
        // 2. 更新账户余额
        Integer balanceBefore = account.getLoveCoin() != null ? account.getLoveCoin() : 0;
        Integer balanceAfter = balanceBefore + amount;
        account.setLoveCoin(balanceAfter);
        account.setTotalEarned((account.getTotalEarned() != null ? account.getTotalEarned() : 0) + amount);
        account.setUpdatedAt(LocalDateTime.now());
        
        // 更新等级（根据累计收入）
        String newLevel = calculateCoinLevel(account.getTotalEarned());
        account.setLevel(newLevel);
        userCoinAccountMapper.updateById(account);
        
        // 检查爱心币余额相关成就
        achievementService.checkCoinBalanceAchievements(userId, balanceAfter);
        
        // 检查累计获得爱心币相关成就
        achievementService.checkTotalEarnedAchievements(userId, account.getTotalEarned());
        
        // 检查等级相关成就
        achievementService.checkLevelAchievements(userId, newLevel);

        // 3. 记录交易
        CoinTransaction transaction = new CoinTransaction();
        transaction.setUserId(userId);
        transaction.setType("earn");
        transaction.setAmount(amount);
        transaction.setFeeAmount(0);
        transaction.setBalanceBefore(balanceBefore);
        transaction.setBalanceAfter(balanceAfter);
        transaction.setSource(source);
        transaction.setTitle(title);
        transaction.setDescription(description);
        transaction.setRelatedId(relatedId);
        transaction.setRelatedType(relatedType);
        transaction.setCreatedAt(LocalDateTime.now());
        return save(transaction);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean transferCoins(Long fromUserId, Long toUserId, Integer amount, String remark) {
        if (amount == null || amount <= 0) {
            throw new BizException(ErrorCode.PARAMS_ERROR, "转账金额必须大于0");
        }
        
        if (fromUserId.equals(toUserId)) {
            throw new BizException(ErrorCode.PARAMS_ERROR, "不能向自己转账");
        }

        // 1. 获取转出用户和转入用户
        UserCoinAccount fromAccount = getUserCoinAccount(fromUserId);
        UserCoinAccount toAccount = getUserCoinAccount(toUserId);
        
        User fromUser = userMapper.selectById(fromUserId);
        if (fromUser == null) {
            throw new BizException(ErrorCode.NOT_FOUND_ERROR, "转出用户不存在");
        }
        
        User toUser = userMapper.selectById(toUserId);
        if (toUser == null) {
            throw new BizException(ErrorCode.NOT_FOUND_ERROR, "转入用户不存在");
        }

        // 2. 检查转出用户是否为VIP会员
        if (fromUser.getIsVip() == null || !fromUser.getIsVip() || fromUser.getVipExpireTime() == null 
            || fromUser.getVipExpireTime().isBefore(LocalDateTime.now())) {
            throw new BizException(ErrorCode.OPERATION_ERROR, "转账功能仅限VIP会员使用");
        }

        // 3. 获取手续费率
        double feeRate = getTransferFeeRate(fromUser);
        Integer feeAmount = (int) Math.ceil(amount * feeRate);
        Integer totalDeduct = amount + feeAmount;

        // 4. 检查余额
        Integer fromBalance = fromAccount.getLoveCoin() != null ? fromAccount.getLoveCoin() : 0;
        if (fromBalance < totalDeduct) {
            throw new BizException(ErrorCode.OPERATION_ERROR, 
                    "爱心币余额不足，需要" + totalDeduct + "（含手续费" + feeAmount + "）");
        }

        // 5. 更新转出账户
        Integer fromBalanceBefore = fromBalance;
        Integer fromBalanceAfter = fromBalance - totalDeduct;
        fromAccount.setLoveCoin(fromBalanceAfter);
        fromAccount.setTotalSpent((fromAccount.getTotalSpent() != null ? fromAccount.getTotalSpent() : 0) + totalDeduct);
        fromAccount.setUpdatedAt(LocalDateTime.now());
        userCoinAccountMapper.updateById(fromAccount);

        // 6. 更新转入账户
        Integer toBalance = toAccount.getLoveCoin() != null ? toAccount.getLoveCoin() : 0;
        Integer toBalanceBefore = toBalance;
        Integer toBalanceAfter = toBalance + amount;
        toAccount.setLoveCoin(toBalanceAfter);
        toAccount.setTotalEarned((toAccount.getTotalEarned() != null ? toAccount.getTotalEarned() : 0) + amount);
        toAccount.setLevel(calculateCoinLevel(toAccount.getTotalEarned()));
        toAccount.setUpdatedAt(LocalDateTime.now());
        userCoinAccountMapper.updateById(toAccount);

        // 7. 记录转出交易
        CoinTransaction transferOut = new CoinTransaction();
        transferOut.setUserId(fromUserId);
        transferOut.setCounterpartyUserId(toUserId);
        transferOut.setType("transfer_out");
        transferOut.setAmount(-amount);
        transferOut.setFeeAmount(feeAmount);
        transferOut.setBalanceBefore(fromBalanceBefore);
        transferOut.setBalanceAfter(fromBalanceAfter);
        transferOut.setSource("transfer");
        transferOut.setTitle("转账给用户" + toUserId);
        transferOut.setDescription("转账给用户" + toUser.getNickname());
        transferOut.setRemark(remark);
        transferOut.setCreatedAt(LocalDateTime.now());
        save(transferOut);

        // 8. 记录转入交易
        CoinTransaction transferIn = new CoinTransaction();
        transferIn.setUserId(toUserId);
        transferIn.setCounterpartyUserId(fromUserId);
        transferIn.setType("transfer_in");
        transferIn.setAmount(amount);
        transferIn.setFeeAmount(0);
        transferIn.setBalanceBefore(toBalanceBefore);
        transferIn.setBalanceAfter(toBalanceAfter);
        transferIn.setSource("transfer");
        transferIn.setTitle("收到用户" + fromUserId + "的转账");
        transferIn.setDescription("收到用户" + fromUser.getNickname() + "的转账");
        transferIn.setRemark(remark);
        transferIn.setCreatedAt(LocalDateTime.now());
        save(transferIn);

        // 检查转账相关成就
        achievementService.checkTransferAchievements(fromUserId, amount);

        return true;
    }

    @Override
    public CoinTransactionDTO convertToCoinTransactionDTO(CoinTransaction transaction) {
        if (transaction == null) {
            return null;
        }
        CoinTransactionDTO dto = new CoinTransactionDTO();
        BeanUtils.copyProperties(transaction, dto);
        return dto;
    }
    
    /**
     * 获取用户爱心币账户，如果不存在则创建
     */
    private UserCoinAccount getUserCoinAccount(Long userId) {
        LambdaQueryWrapper<UserCoinAccount> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserCoinAccount::getUserId, userId);
        UserCoinAccount account = userCoinAccountMapper.selectOne(wrapper);
        
        if (account == null) {
            // 初始化账户
            account = new UserCoinAccount();
            account.setUserId(userId);
            account.setLoveCoin(0);
            account.setTotalEarned(0);
            account.setTotalSpent(0);
            account.setLevel("铜牌"); // 默认铜牌等级
            account.setCreatedAt(LocalDateTime.now());
            account.setUpdatedAt(LocalDateTime.now());
            userCoinAccountMapper.insert(account);
        }
        
        return account;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> upgradeLevel(Long userId) {
        UserCoinAccount account = getUserCoinAccount(userId);
        
        String currentLevelStr = account.getLevel() != null ? account.getLevel() : "铜牌";
        int currentLevelNum = getLevelNumber(currentLevelStr);
        int nextLevelNum = currentLevelNum + 1;
        
        // 如果已经是最高等级，无法升级
        if (nextLevelNum > 6) {
            Map<String, Object> result = new HashMap<>();
            result.put("success", false);
            result.put("message", "已达到最高等级");
            result.put("current_level", currentLevelStr);
            return result;
        }
        
        // 获取升级所需的爱心币
        int upgradeCost = getUpgradeCost(nextLevelNum);
        String nextLevelStr = getLevelName(nextLevelNum);
        
        // 如果是升级到铜牌（默认等级），直接升级
        if (nextLevelNum == 1) {
            account.setLevel(nextLevelStr);
            account.setUpdatedAt(LocalDateTime.now());
            userCoinAccountMapper.updateById(account);
            
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("message", "已获得初始铜牌等级！");
            result.put("old_level", currentLevelStr);
            result.put("new_level", nextLevelStr);
            result.put("upgrade_cost", 0);
            return result;
        }
        
        // 检查余额是否足够
        Integer currentBalance = account.getLoveCoin() != null ? account.getLoveCoin() : 0;
        if (currentBalance < upgradeCost) {
            Map<String, Object> result = new HashMap<>();
            result.put("success", false);
            result.put("message", "爱心币余额不足，升级需要" + upgradeCost + "爱心币");
            result.put("current_level", currentLevelStr);
            result.put("next_level", nextLevelStr);
            result.put("upgrade_cost", upgradeCost);
            result.put("current_balance", currentBalance);
            return result;
        }
        
        // 扣除升级费用
        boolean deductSuccess = spendCoins(
            userId, 
            upgradeCost, 
            "level_upgrade", 
            "等级升级",
            "升级到" + nextLevelStr,
            null,
            null
        );
        
        if (!deductSuccess) {
            Map<String, Object> result = new HashMap<>();
            result.put("success", false);
            result.put("message", "扣除升级费用失败");
            return result;
        }
        
        // 更新等级
        account.setLevel(nextLevelStr);
        account.setUpdatedAt(LocalDateTime.now());
        userCoinAccountMapper.updateById(account);
        
        // 检查等级相关成就
        achievementService.checkLevelAchievements(userId, nextLevelStr);
        
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("message", "升级成功！");
        result.put("old_level", currentLevelStr);
        result.put("new_level", nextLevelStr);
        result.put("upgrade_cost", upgradeCost);
        
        return result;
    }
    
    /**
     * 获取下一等级所需累计收入
     */
    private int getNextLevelRequired(int currentLevel) {
        switch (currentLevel) {
            case 0: return 1;        // 1分
            case 1: return 10000;    // 100元
            case 2: return 100000;   // 1000元
            case 3: return 500000;   // 5000元
            case 4: return 1000000;  // 10000元
            default: return Integer.MAX_VALUE;
        }
    }

    /**
     * 根据累计收入计算爱心币等级
     * @param totalEarned 累计收入（以分为单位）
     * @return 等级
     */
    private String calculateCoinLevel(Integer totalEarned) {
        if (totalEarned == null || totalEarned <= 0) {
            return "0";
        }
        
        // 示例等级规则（以分为单位）
        if (totalEarned >= 1000000) { // 10000元
            return "5";
        } else if (totalEarned >= 500000) { // 5000元
            return "4";
        } else if (totalEarned >= 100000) { // 1000元
            return "3";
        } else if (totalEarned >= 10000) { // 100元
            return "2";
        } else {
            return "1";
        }
    }
    
    /**
     * 获取用户转账手续费率
     * @param user 用户信息
     * @return 手续费率（0-1之间）
     */
    private double getTransferFeeRate(User user) {
        // 如果用户不是VIP或VIP已过期，使用默认费率
        if (user.getIsVip() == null || !user.getIsVip() || user.getVipExpireTime() == null 
            || user.getVipExpireTime().isBefore(java.time.LocalDateTime.now())) {
            return DEFAULT_TRANSFER_FEE_RATE;
        }
        
        // 如果用户有VIP套餐，获取对应的手续费率
        if (user.getVipPlanId() != null) {
            VipPlan vipPlan = vipPlanMapper.selectById(user.getVipPlanId());
            if (vipPlan != null && vipPlan.getTransferFeeRate() != null) {
                return vipPlan.getTransferFeeRate().doubleValue();
            }
        }
        
        // 如果找不到VIP套餐配置，使用默认费率
        return DEFAULT_TRANSFER_FEE_RATE;
    }
    
    /**
     * 获取等级名称
     * @param levelNum 等级数字（1-6）
     * @return 等级名称
     */
    private String getLevelName(int levelNum) {
        switch (levelNum) {
            case 1: return "铜牌";
            case 2: return "银牌";
            case 3: return "金牌";
            case 4: return "钻石";
            case 5: return "大师";
            case 6: return "传说";
            default: return "铜牌";
        }
    }
    
    /**
     * 获取等级数字
     * @param levelName 等级名称
     * @return 等级数字（1-6）
     */
    private int getLevelNumber(String levelName) {
        if (levelName == null) return 0;
        
        switch (levelName) {
            case "铜牌": return 1;
            case "银牌": return 2;
            case "金牌": return 3;
            case "钻石": return 4;
            case "大师": return 5;
            case "传说": return 6;
            default: return 0;
        }
    }
    
    /**
     * 获取升级所需费用
     * @param targetLevel 目标等级数字（1-6）
     * @return 升级费用（爱心币）
     */
    private int getUpgradeCost(int targetLevel) {
        switch (targetLevel) {
            case 1: return 0;      // 铜牌：默认等级，免费
            case 2: return 1000;   // 银牌：1000爱心币
            case 3: return 5000;   // 金牌：5000爱心币
            case 4: return 15000;  // 钻石：15000爱心币
            case 5: return 50000;  // 大师：50000爱心币
            case 6: return 100000; // 传说：100000爱心币
            default: return 0;
        }
    }
}
